class Node {
  constructor(val) {
    this.val = val;
    this.next = null;
  }
}

class LinkedList {
  constructor() {
    this.headNode = null;
    this.endNode = null;
    this.length = 0;
  }

  /**
   * 得指定index node和前一个node
   * @param {*} index 当前index
   * @param {*} that 对象实例
   * @returns
   */
  static getPreAndCurrent(index, that) {
    let preNode = null;
    let currNode = null;
    if (index <= that.length) {
      if (index !== 0) {
        preNode = that.getIndexVal(index - 1);
      }
      currNode = that.getIndexVal(index);
    }
    return {
      preNode,
      currNode,
    };
  }

  /**
   * 超界
   * @param {*} index 当前index
   * @param {*} that 对象实例
   */
  static IndexOut(index, that) {
    if (index < 0 || index >= that.length) {
      throw new Error("下标超出");
    }
  }

  append(val) {
    const node = new Node(val);
    /**
     * 链表为空时，头和尾都是当前添加的node
     * 链表不为空时，尾节点添加next为当前节点，然后设置新的尾节点尾当期节点
     */
    if (!this.headNode) {
      this.headNode = node;
      this.endNode = node;
    } else {
      this.endNode.next = node;
      this.endNode = node;
    }
    this.length++;
  }

  preAppend(val) {
    const node = new Node(val);
    node.next = this.headNode;
    this.headNode = node;
    this.length++;
  }

  /**
   * 根据索引的值
   */
  getIndexVal(index) {
    let count = 0;
    let currentNode = this.headNode;
    while (count < index) {
      currentNode = currentNode.next;
      count++;
    }
    return currentNode;
  }

  /** 插入 */
  insert(val, index) {
    if (index >= this.length) {
      this.append(val);
    } else {
      const node = new Node(val);
      const { preNode, currNode } = LinkedList.getPreAndCurrent(index, this);
      if (index === 0) {
        this.headNode = node;
      } else {
        preNode.next = node;
      }
      node.next = currNode;
      this.length++;
    }
  }

  /** 删除 */
  remove(index) {
    LinkedList.IndexOut(index, this);
    const { preNode } = LinkedList.getPreAndCurrent(index, this);
    const nextNode = this.getIndexVal(index + 1);
    if (index === 0) {
      this.headNode = nextNode;
    } else {
      preNode.next = nextNode;
    }
    this.length--;
    /** index为之前的被删除的，this.length已经--，现在this.length等于传入的index */
    if (index === this.length) {
      /** 取新链表的最后一个 */
      this.endNode = this.getIndexVal(this.length - 1);
    }
  }

  /** 反转 */
  reverse() {
    let previousNode = null;
    let currentNode = this.headNode;

    while (currentNode !== null) {
      let nextNode = currentNode.next;
      currentNode.next = previousNode;
      previousNode = currentNode;
      currentNode = nextNode;
    }

    this.headNode = previousNode;
  }
}

const testLinked = new LinkedList();
testLinked.append(2);
testLinked.append(4);
testLinked.preAppend(1);
testLinked.insert("insert", 4);
testLinked.remove(2);
console.log(testLinked);
console.log(testLinked.getIndexVal(3), testLinked.endNode);
